package com.koi.generator.service.gentable;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.koi.common.ex.koi.YUtil;
import com.koi.common.satoken.KoiLoginUtil;
import com.koi.generator.constants.TemplateConstant;
import com.koi.generator.pojo.GenCode;
import com.koi.generator.pojo.TemplatePathParam;
import com.koi.generator.service.gencloumn.GenColumnService;
import com.koi.generator.utils.FreeMarkerTemplateUtil;
import com.koi.generator.utils.MySQLToJavaTypeUtil;
import com.koi.generator.utils.StringHumpUtil;
import com.koi.plus.mapper.gen.GenTableMapper;
import com.koi.pojo.gen.GenColumn;
import com.koi.pojo.gen.GenTable;
import com.koi.pojo.gen.TableColumn;
import com.koi.pojo.gen.TableData;
import freemarker.template.Template;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ･ᴗ･
 * @description [代码生成业务表-服务实现层]
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class GenTableServiceImpl extends ServiceImpl<GenTableMapper, GenTable> implements GenTableService {

    private final GenTableMapper genTableMapper;

    private final GenColumnService genColumnService;

    /**
     * @description [获取指定数据库下的所有表名称及注释-导入表格数据]
     * @author ･ᴗ･
     */
    @Override
    public Map<String, Object> listAllTableName(TableData vo) {
        LambdaQueryWrapper<GenTable> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(GenTable::getTableName);
        List<GenTable> genTableList = genTableMapper.selectList(wrapper);
        List<String> tableNameList = null;
        // 筛选出未导入表格的数据
        if(CollectionUtil.isNotEmpty(genTableList)){
            tableNameList = genTableList.parallelStream().map(GenTable::getTableName).collect(Collectors.toList());
        }
        List<TableData> allTableNameList = genTableMapper.getAllTableName(vo, tableNameList);
        Integer pageNo = vo.getPageNo();
        Integer pageSize = vo.getPageSize();
        String tableSchema = vo.getTableSchema();
        String tableName = vo.getTableName();
        // 计算起始索引和结束索引
        int startIndex = (pageNo - 1) * pageSize;
        int endIndex = Math.min(startIndex + pageSize, allTableNameList.size());
        // 如果有条件，先进行过滤，在进行分页显示
        List<TableData> filteredList = allTableNameList.stream()
                .filter(tableData -> (tableSchema.isEmpty() || tableData.getTableSchema().contains(tableSchema)))
                .filter(tableData -> (tableName.isEmpty() || tableData.getTableName().contains(tableName)))
                .collect(Collectors.toList());
        // 使用Stream对列表进行分页操作
        List<TableData> records = filteredList.stream()
                .skip(startIndex)  // 跳过前startIndex条记录
                .limit(endIndex - startIndex)  // 取出当前页的记录
                .collect(Collectors.toList());  // 将结果转换为List
        Map<String, Object> map = new HashMap<>();
        map.put("total", allTableNameList.size()); // 总条数
        map.put("current", vo.getPageNo()); // 当前第几页
        map.put("size", vo.getPageSize()); // 每页显示多少条
        map.put("pages", (int) Math.ceil((double) allTableNameList.size() / pageSize)); // 总共多少页
        map.put("records", records); // 当前页的记录
        return map;
    }

    /**
     * @description [导入数据]
     * @author ･ᴗ･
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importGenTable(TableData vo) {
        // 根据表名和数据库名查询表相关信息
        List<TableData> assignTableList = this.getAssignTable(vo.getTableSchema(), vo.getTableNameList());
        YUtil.isTrue(CollectionUtils.isEmpty(assignTableList), "请检查数据库是否存在此表名");
        List<GenTable> genTableList = new ArrayList<>();
        // 导入表数据
        for (TableData tableData : assignTableList) {
            GenTable genTable = new GenTable();
            genTable.setTableName(tableData.getTableName());
            if(StringUtils.isNotBlank(vo.getTableSchema())){
                genTable.setTableSchema(vo.getTableSchema());
            }
            genTable.setClassName(StringHumpUtil.getBigHump(tableData.getTableName()));
            genTable.setTableComment(tableData.getTableComment());
            genTable.setPageFolder(StringHumpUtil.getSmallHump(tableData.getTableName()));
            genTable.setCreateBy(KoiLoginUtil.getUserName());
            genTable.setCreateTime(new Date());
            genTableList.add(genTable);
            // 查询该表列字段相关数据
            List<TableColumn> tableColumnList = this.getTableColumn(vo.getTableSchema(), tableData.getTableName());
            List<GenColumn> genColumnList = new ArrayList<>();
            for (TableColumn tableColumn : tableColumnList) {
                GenColumn genColumn = new GenColumn();
                // 未传递值，默认是local，当前数据库
                if(StringUtils.isNotBlank(vo.getTableSchema())){
                    genColumn.setTableSchema(vo.getTableSchema());
                }
                genColumn.setTableName(tableData.getTableName());
                genColumn.setIsPk(tableColumn.getIsPk());
                genColumn.setColumnName(tableColumn.getColumnName());
                genColumn.setColumnType(tableColumn.getColumnType());
                genColumn.setIsNullable(tableColumn.getIsNullable());
                genColumn.setJavaType(MySQLToJavaTypeUtil.convert(tableColumn.getColumnType()));
                genColumn.setJavaField( StringHumpUtil.getSmallHump(tableColumn.getColumnName()));
                genColumn.setColumnComment(tableColumn.getColumnComment());
                genColumn.setCreateBy(KoiLoginUtil.getUserName());
                // 若是主键，逻辑判断
                String isPk = genColumn.getIsPk();
                if (isPk.equals("0")) {
                    genColumn.setIsSearch("1");
                    genColumn.setIsForm("1");
                    genColumn.setIsRule("1");
                }
                // 类型判断
                if (genColumn.getColumnType().equals("char")) {
                    genColumn.setElementType("select");
                }
                if (genColumn.getColumnType().equals("datetime")) {
                    genColumn.setElementType("datetime");
                }
                // 修改时间
                if (genColumn.getJavaField().equals("createBy") || genColumn.getJavaField().equals("updateBy") || genColumn.getJavaField().equals("updateTime")) {
                    genColumn.setIsList("1");
                    genColumn.setIsSearch("1");
                    genColumn.setIsForm("1");
                    genColumn.setIsRule("1");
                }
                // 创建时间
                if (genColumn.getJavaField().equals("createTime")) {
                    genColumn.setIsSearch("1");
                    genColumn.setIsForm("1");
                    genColumn.setIsRule("1");
                }
                genColumnList.add(genColumn);
            }
            YUtil.isTrue(!genColumnService.saveBatch(genColumnList), "列导入失败，请稍后重试");
        }
        YUtil.isTrue(!this.saveBatch(genTableList), "表导入失败，请稍后重试");
    }

    /**
     * @description [同步数据]
     * @author ･ᴗ･
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void synchronousData(String tableSchema, String tableName) {
        GenTable genTable = this.getOne(new LambdaQueryWrapper<GenTable>().eq(GenTable::getTableName, tableName));
        YUtil.isTrue(ObjectUtils.isEmpty(genTable), "此表未进行导入操作");
        // 获取数据库名称，若是local，则默认当前数据库
        if(tableSchema.equals("local")) {
            tableSchema = null;
        }
        // 同步表数据-根据表名和数据库名查询表相关信息
        List<TableData> assignTableList = this.getAssignTable(tableSchema, Collections.singletonList(tableName));
        YUtil.isTrue(CollectionUtils.isEmpty(assignTableList), "请检查数据库是否存在此表名");
        TableData tableData = assignTableList.get(0);
        LambdaUpdateWrapper<GenTable> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(GenTable::getPageFolder, StringHumpUtil.getSmallHump(tableData.getTableName()));
        updateWrapper.set(GenTable::getTableComment, tableData.getTableComment());
        updateWrapper.eq(GenTable::getTableName, tableName);
        this.update(updateWrapper);
        // 先删除该表生成的列数据
        genColumnService.remove(new LambdaQueryWrapper<GenColumn>().eq(GenColumn::getTableName, tableName));
        // 同步列数据-根据表名进行生成列
        List<TableColumn> tableColumnList = this.getTableColumn(tableSchema, tableName);
        List<GenColumn> genColumnList = new ArrayList<>();
        for (TableColumn tableColumn : tableColumnList) {
            GenColumn genColumn = new GenColumn();
            genColumn.setTableSchema(tableSchema);
            genColumn.setTableName(tableName);
            genColumn.setIsPk(tableColumn.getIsPk());
            genColumn.setColumnName(tableColumn.getColumnName());
            genColumn.setColumnType(tableColumn.getColumnType());
            genColumn.setIsNullable(tableColumn.getIsNullable());
            genColumn.setJavaType(MySQLToJavaTypeUtil.convert(tableColumn.getColumnType()));
            genColumn.setJavaField(StringHumpUtil.getSmallHump(tableColumn.getColumnName()));
            genColumn.setColumnComment(tableColumn.getColumnComment());
            genColumn.setCreateBy(KoiLoginUtil.getUserName());
            // 若是主键，逻辑判断
            String isPk = genColumn.getIsPk();
            if (isPk.equals("0")) {
                genColumn.setIsSearch("1");
                genColumn.setIsForm("1");
                genColumn.setIsRule("1");
            }
            // 类型判断
            if (genColumn.getColumnType().equals("char")) {
                genColumn.setElementType("select");
            }
            if (genColumn.getColumnType().equals("datetime")) {
                genColumn.setElementType("datetime");
            }
            // 修改时间
            if (genColumn.getJavaField().equals("createBy") || genColumn.getJavaField().equals("updateBy") || genColumn.getJavaField().equals("updateTime")) {
                genColumn.setIsList("1");
                genColumn.setIsSearch("1");
                genColumn.setIsForm("1");
                genColumn.setIsRule("1");
            }
            // 创建时间
            if (genColumn.getJavaField().equals("createTime")) {
                genColumn.setIsSearch("1");
                genColumn.setIsForm("1");
                genColumn.setIsRule("1");
            }
            genColumnList.add(genColumn);
        }
        YUtil.isTrue(!genColumnService.saveBatch(genColumnList), "列导入失败，请稍后重试");
    }

    /**
     * @param tableSchema 数据库名
     * @param tableList 生成表名集合
     * @description [获取指定数据库下的指定表详细数据]
     * @author ･ᴗ･
     */
    @Override
    public List<TableData> getAssignTable(String tableSchema, List<String> tableList) {
        return genTableMapper.getAssignTable(tableSchema, tableList);
    }

    /**
     * @param tableSchema 数据库名称
     * @param tableName 表名
     * @description [获取指定数据库和表名的列字段数据]
     * @author ･ᴗ･
     */
    @Override
    public List<TableColumn> getTableColumn(String tableSchema, String tableName) {
        return genTableMapper.getTableColumn(tableSchema, tableName);
    }

    /**
     * @param genCodeList 生成代码数据库名称 和 表名称
     * @param type 类型 [preview-预览代码 gen-生成代码]
     * @description [通过前端生成代码]
     * @author ･ᴗ･
     */
    @Override
    public Map<String, Object> generatePerfectCode(List<GenCode> genCodeList, String type) {
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        StringBuilder tableMsg = new StringBuilder();
        tableMsg.append("失败的表名：");
        List<GenTable> genTableList = new ArrayList<>();
        for (GenCode genCode : genCodeList) {
            LambdaQueryWrapper<GenTable> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(GenTable::getTableSchema, genCode.getTableSchema());
            wrapper.eq(GenTable::getTableName, genCode.getTableName());
            GenTable genTable = this.getOne(wrapper);
            if(ObjectUtil.isNotEmpty(genTable)) {
                genTableList.add(genTable);
            } else {
                tableMsg.append("[数据库：" + genCode.getTableSchema() + "-表名：" + genCode.getTableName() + "]");
            }
        }
        YUtil.isTrue(tableMsg.length() > 7, String.valueOf(tableMsg));
        YUtil.isTrue(CollectionUtils.isEmpty(genTableList), "请检查选中的数据是否进行导入操作");
        TemplatePathParam templatePathParam = null;
        // 预览文件
        Map<String, Object> previewMap = new HashMap<>();
        try {
            /* 获取gen_table中导入的表相关信息 */
            for (GenTable genTable : genTableList) {
                /**
                 * 参数1：projectName 生成代码的项目路径
                 * 参数2：packageName 包名 com.koi.generator（必须为三级目录，否则无法生成）
                 */
                // 模版路径等配置
                if(genTable.getGenPath().equals("local")) {
                    // 获取用户桌面路径
                    String desktopPath = System.getProperty("user.home") + "/" + "Desktop" + "/" + "KOI-ADMIN-CODE";
                    templatePathParam = new TemplatePathParam(desktopPath, genTable.getPackagePath());
                } else {
                    // 指定路径，例如：C://Koi-Admin-GenCode
                    templatePathParam = new TemplatePathParam(genTable.getGenPath(), genTable.getPackagePath());
                }
                // 表名：例如：[sys_login_user]
                String tableName = genTable.getTableName();
                String tableSchema = genTable.getTableSchema();
                List<GenColumn> genColumnList = genColumnService.list(new LambdaQueryWrapper<GenColumn>().eq(GenColumn::getTableName, tableName).eq(GenColumn::getTableSchema, tableSchema));
                log.info("[<------------------------- 正在生成･ᴗ･[{}] ------------------------->]", tableName);
                // 生成实体类
                String pojo = generatePojoFile(templatePathParam, genTable, genColumnList, type);

                // 生成vo类
                String vo = generateVoFile(templatePathParam, genTable, genColumnList, type);

                // 生成bo类
                String bo = generateBoFile(templatePathParam, genTable, genColumnList, type);

                // 生成dto类
                // String dto = generateDtoFile(templatePathParam, genTable, genColumnList, type);

                // 生成Mapper
                String mapper = generateMapperFile(templatePathParam, genTable, type);

                // 生成Mapper.xml
                String mapperXml = generateMapperXmlFile(templatePathParam, genTable, type);

                // 生成service接口
                String service = generateServiceFile(templatePathParam, genTable, type);

                // 生成serviceImpl实现类
                String serviceImpl = generateServiceImplFile(templatePathParam, genTable, type);

                // 生成Controller类
                String controller = generateControllerFile(templatePathParam, genTable, genColumnList, type);

                // 生成api/index.ts文件
                String api = generateApiFile(templatePathParam, genTable, type);

                // 生成vue文件
                String vue = generateVueFile(templatePathParam, genTable, genColumnList, type);

                // 生成application.yml文件
                // generateApplicationYmlFile(templatePathParam, tableClass, allColumnList, type);

                // 预览代码
                if(type.equals("preview")) {
                    previewMap.put("pojo", pojo);
                    previewMap.put("vo", vo);
                    previewMap.put("bo", bo);
                    previewMap.put("mapper", mapper);
                    previewMap.put("mapperXml", mapperXml);
                    previewMap.put("service", service);
                    previewMap.put("serviceImpl", serviceImpl);
                    previewMap.put("controller", controller);
                    previewMap.put("api", api);
                    previewMap.put("vue", vue);
                }

                successNum++;
                successMsg.append("<br/>").append(successNum).append("、成功表名：[").append(tableName).append("]");
                log.info("成功信息：{}", successMsg);
                return previewMap;
            }
        } catch (Exception e) {
            failureNum++;
            failureMsg.append("<br/>").append(failureNum).append("、失败表名：[").append(failureMsg).append("]");
            log.error("代码生成失败：{}: {}", e.getMessage(), failureMsg);
            e.printStackTrace();
            YUtil.isTrue("代码生成失败");
        }
        log.info("finshMsg：{}", "全部生成成功");
        return previewMap;
    }

    /**
     * @description [生成pojo实体类]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     * @param genColumnList 表所有列数据
     */
    private String generatePojoFile(TemplatePathParam templatePathParam, GenTable genTable, List<GenColumn> genColumnList, String type) {
        try {
            // 文件后缀名
            String suffix = ".java";
            // 生成文件所在目录绝对路径
            String folderPath = templatePathParam.getEntityPath();
            // 生成文件绝对路径
            String filePath = templatePathParam.getEntityPath() + "/" + StringHumpUtil.getBigHump(genTable.getTableName()) + suffix;

            Map<String, Object> dataMap = new HashMap<>();
            // 列相关信息
            dataMap.put("tableColumnList", genColumnList);
            // 表相关信息
            dataMap = getCommonModel(templatePathParam, dataMap, genTable);
            if(type.equals("preview")) {
                // 预览代码
                return previewFileByTemplate(TemplateConstant.entityTemplate, dataMap);
            }
            if(type.equals("gen")) {
                generateFileByTemplate(TemplateConstant.entityTemplate, folderPath, filePath, dataMap);
                log.info("[<------------------------- 生成实体类成功･ᴗ･ ------------------------->]");
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
        return "预览失败";
    }

    /**
     * @description [生成Vo类文件]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     * @param genColumnList 表所有列数据
     */
    private String generateVoFile(TemplatePathParam templatePathParam, GenTable genTable, List<GenColumn> genColumnList, String type) throws Exception {
        String suffix = "Vo.java";
        String folderPath = templatePathParam.getEntityVoPath();
        String filePath = templatePathParam.getEntityVoPath() + "/" + StringHumpUtil.getBigHump(genTable.getTableName()) + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("tableColumnList", genColumnList);
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.entityVoTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.entityVoTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成Vo类成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成Bo类]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     * @param genColumnList 表所有列数据
     */
    private String generateBoFile(TemplatePathParam templatePathParam, GenTable genTable, List<GenColumn> genColumnList, String type) throws Exception {
        String suffix = "Bo.java";
        String folderPath = templatePathParam.getEntityBoPath();
        String filePath = templatePathParam.getEntityBoPath() + "/" + StringHumpUtil.getBigHump(genTable.getTableName()) + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("tableColumnList", genColumnList);
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.entityBoTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.entityBoTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成Bo类成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成Dto类]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     * @param genColumnList 表所有列数据
     */
    private String generateDtoFile(TemplatePathParam templatePathParam, GenTable genTable, List<GenColumn> genColumnList, String type) throws Exception {
        String suffix = "Dto.java";
        String folderPath = templatePathParam.getEntityDtoPath();
        String filePath = templatePathParam.getEntityDtoPath() + "/" + StringHumpUtil.getBigHump(genTable.getTableName()) + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("tableColumnList", genColumnList);
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.entityDtoTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.entityDtoTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成Dto类成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成mapper文件]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     */
    private String generateMapperFile(TemplatePathParam templatePathParam, GenTable genTable, String type) throws Exception {
        String suffix = "Mapper.java";
        String folderPath = templatePathParam.getMapperPath();
        String filePath = templatePathParam.getMapperPath() + "/"+ StringHumpUtil.getBigHump(genTable.getTableName()) + suffix;
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.mapperTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.mapperTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成Mapper类成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成xml映射文件]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     */
    private String generateMapperXmlFile(TemplatePathParam templatePathParam, GenTable genTable, String type) throws Exception {
        String suffix = "Mapper.xml";
        String folderPath = templatePathParam.getMapperXmlPath();
        String filePath = templatePathParam.getMapperXmlPath() + "/" + StringHumpUtil.getBigHump(genTable.getTableName()) + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.mapperXmlTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.mapperXmlTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成Mapper.xml映射文件成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成业务接口层文件]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     */
    private String generateServiceFile(TemplatePathParam templatePathParam, GenTable genTable, String type) throws Exception {
        String suffix = "Service.java";
        String folderPath = templatePathParam.getServicePath();
        String filePath = templatePathParam.getServicePath() + "/" + StringHumpUtil.getBigHump(genTable.getTableName()) + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.serviceTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.serviceTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成service接口･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成业务实现层文件]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     */
    private String generateServiceImplFile(TemplatePathParam templatePathParam, GenTable genTable, String type) throws Exception {
        String suffix = "ServiceImpl.java";
        String folderPath = templatePathParam.getServiceImplPath();
        String filePath = templatePathParam.getServiceImplPath() + "/" + StringHumpUtil.getBigHump(genTable.getTableName()) + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.serviceImplTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.serviceImplTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成serviceImpl实现类成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成控制层文件]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     * @param genColumnList 表所有列数据
     */
    private String generateControllerFile(TemplatePathParam templatePathParam, GenTable genTable, List<GenColumn> genColumnList, String type) throws Exception {
        String suffix = "Controller.java";
        String folderPath = templatePathParam.getControllerPath();
        String filePath = templatePathParam.getControllerPath() + "/" + StringHumpUtil.getBigHump(genTable.getTableName()) + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("tableColumnList", genColumnList);
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.controllerTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.controllerTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成Controller层文件成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成Pom文件]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     */
    private String generatePomFile(TemplatePathParam templatePathParam, GenTable genTable, String type) throws Exception {
        String suffix = "pom.xml";
        String folderPath = templatePathParam.getPomPath();
        String filePath = templatePathParam.getPomPath() + "/" + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.pomTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.pomTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成Pom文件成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成application.yml文件]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     */
    private String generateApplicationYmlFile(TemplatePathParam templatePathParam, GenTable genTable, String type) throws Exception {
        String suffix = "application.yml";
        String folderPath = templatePathParam.getApplicationYmlPath();
        String filePath = templatePathParam.getApplicationYmlPath() + "/" + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.applicationTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.applicationTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成application.yml文件成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @description [生成api/index.ts文件]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param genTable 表数据
     */
    private String generateApiFile(TemplatePathParam templatePathParam, GenTable genTable, String type) throws Exception {
        // 根据数据库名查询 前端模块文件夹名称 AND 前端页面文件夹名称
        String suffix = "index.ts";
        // 文件路径生成
        String folderPath = templatePathParam.getApiPath() + "/" + genTable.getModuleFolder() + "/" + genTable.getPageFolder();
        // 文件生成
        String filePath = folderPath + "/" + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if(type.equals("preview")) {
            // 预览代码
            return previewFileByTemplate(TemplateConstant.apiTemplate, dataMap);
        }
        if(type.equals("gen")) {
            generateFileByTemplate(TemplateConstant.apiTemplate, folderPath, filePath, dataMap);
            log.info("[<------------------------- 生成Api接口成功･ᴗ･ ------------------------->]");
        }
        return "预览失败";
    }

    /**
     * @param templatePathParam 生成模版路径配置
     * @param genTable          表数据
     * @param genColumnList     表所有列数据
     * @description [生成vue文件]
     * <#if modelColumn?exists> 只检查变量或键是否存在，而<#if modelColumn??> 则检查变量是否存在且不为空。
     * @author ･ᴗ･
     */
    private String generateVueFile(TemplatePathParam templatePathParam, GenTable genTable, List<GenColumn> genColumnList, String type) throws Exception {
        String suffix = "index.vue";
        // 生成文件所在目录绝对路径
        String folderPath = templatePathParam.getVuePath() + "/" + genTable.getModuleFolder() + "/" + genTable.getPageFolder();
        // 生成文件绝对路径
        String filePath = folderPath + "/" + suffix;

        Map<String, Object> dataMap = new HashMap<String, Object>();
        // 若是下拉框、单选框、多选框必须得有字典类型值才会生成，若是没有则生成示例代码
        dataMap.put("tableColumnList", genColumnList);
        // 组装模版通用参数
        dataMap = getCommonModel(templatePathParam, dataMap, genTable);
        if (genTable.getTableTemplate().equals("table")) {
            if(type.equals("preview")) {
                // 预览代码
                return previewFileByTemplate(TemplateConstant.tableVueTemplate, dataMap);
            }
            if(type.equals("gen")) {
                // 通过Freemarker生成文件
                generateFileByTemplate(TemplateConstant.tableVueTemplate, folderPath, filePath, dataMap);
                log.info("[<------------------------- 生成Table-Vue页面成功･ᴗ･ ------------------------->]");
            }
        }
        if (genTable.getTableTemplate().equals("tree")) {
            if(type.equals("preview")) {
                // 预览代码
                return previewFileByTemplate(TemplateConstant.treeVueTemplate, dataMap);
            }
            if(type.equals("gen")) {
                // 通过Freemarker生成文件
                generateFileByTemplate(TemplateConstant.treeVueTemplate, folderPath, filePath, dataMap);
                log.info("[<------------------------- 生成Tree-Vue页面成功･ᴗ･ ------------------------->]");
            }

        }
        return "预览失败";

    }

    /**
     * @description [模版通用参数]
     * @author ･ᴗ･
     * @param templatePathParam 生成模版路径配置
     * @param dataMap 数据模型
     * @param genTable 表名和表注释参数
     */
    public Map<String, Object> getCommonModel(TemplatePathParam templatePathParam, Map<String, Object> dataMap, GenTable genTable) {
        dataMap.put("tableName", genTable.getTableName()); // sys_login_user
        dataMap.put("tableNameBig", StringHumpUtil.getBigHump(genTable.getTableName())); // SysLoginUser
        dataMap.put("tableNameSmall", StringHumpUtil.getSmallHump(genTable.getTableName())); // sysLoginUser
        dataMap.put("author", genTable.getAuthor());
        dataMap.put("date", templatePathParam.getCurrentDate());
        dataMap.put("tableTemplate", genTable.getTableTemplate());
        // Java字段格式
        if(genTable.getTableTemplate().equals("tree")) {
            dataMap.put("treeId", StringHumpUtil.getSmallHump(genTable.getTreeId()));
            dataMap.put("treePid", StringHumpUtil.getSmallHump(genTable.getTreePid()));
            dataMap.put("treeName", StringHumpUtil.getSmallHump(genTable.getTreeName()));
            // 数据库字段格式
            dataMap.put("treeColumnId", genTable.getTreeId());
            dataMap.put("treeColumnPid", genTable.getTreePid());
            dataMap.put("treeColumnName", genTable.getTreeName());
        }
        dataMap.put("moduleFolder", genTable.getModuleFolder());
        dataMap.put("pageFolder", genTable.getPageFolder());
        dataMap.put("tableComment", StringUtils.isNotBlank(genTable.getTableComment()) ? genTable.getTableComment() : null);
        dataMap.put("packageName", templatePathParam.getPackageName());
        dataMap.put("projectName", templatePathParam.getProjectName());
        return dataMap;
    }

    /**
     * @description [生成文件模版方法]
     * @author ･ᴗ･
     * @param templateName 模版名称
     * @param folderPath 文件夹绝对路径
     * @param filePath 生成文件绝对路径
     * @param dataMap 数据模型
     */
    private void generateFileByTemplate(String templateName, String folderPath, String filePath, Map<String, Object> dataMap) throws Exception {
        Template template = FreeMarkerTemplateUtil.getTemplate(templateName);
        log.info("生成文件绝对路径：[{}]", filePath);
        // // 文件夹不存在创建文件夹
        // File mkFolderPath = new File(folderPath);
        // if (!mkFolderPath.exists() && !mkFolderPath.isDirectory()) {
        //     mkFolderPath.mkdirs();
        // }
        // // 文件不存在创建文件
        // File mkFilePath = new File(filePath);
        // if (!mkFilePath.exists()) {
        //     try {
        //         mkFilePath.createNewFile();
        //     } catch (Exception e) {
        //         e.printStackTrace();
        //     }
        // }
        // 创建文件夹
        Path mkFolderPath = Paths.get(folderPath);
        Files.createDirectories(mkFolderPath);

        // 创建文件
        Path mkFilePath = Paths.get(filePath);
        if (!Files.exists(mkFilePath)) {
            Files.createFile(mkFilePath);
        }
        FileOutputStream fos = new FileOutputStream(String.valueOf(mkFilePath));
        Writer out = new BufferedWriter(new OutputStreamWriter(fos, StandardCharsets.UTF_8), 10240);
        template.process(dataMap, out);
    }

    /**
     * @description [预览文件]
     * @author ･ᴗ･
     */
    private String previewFileByTemplate(String templateName, Map<String, Object> dataMap) throws Exception {
        Template template = FreeMarkerTemplateUtil.getTemplate(templateName);
        StringWriter writer = new StringWriter();
        template.process(dataMap, writer);
        return writer.toString();
    }

}
